/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.chframework.boot.web.interceptors;

import com.chframework.boot.web.support.WebMvcHelper;
import com.chframework.common.constant.ApplicationConstant;
import com.chframework.common.extend.ServletHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;

/**
 * 线程池场景下的 日志拦截器
 * <p>
 * 在使用线程池的场景下，我们的MDC是无法在父子线程之间传递值的，为了满足这个应用场景，我们选择使用阿里的TTL包提供的API来解决应用问题
 * 请注意，多个拦截器的执行顺序只与在注册时的添加顺序有关
 */
@Slf4j
@Component
public class ServiceLogThreadPoolInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (WebMvcHelper.skipIntercept(request, handler)) {
            return true;
        }

        //* 允许所有的子线程继承Session【不适用于线程池场景】
        ServletHelper.exposeRequestAttributes();

        String[] stackTraceArray = Arrays.stream(Thread.currentThread().getStackTrace())
                .map(StackTraceElement::toString)
                .toArray(String[]::new);
        log.debug("ServiceLogThreadPoolInterceptor.preHandle\r\n请求路径：{}\r\n\r\tat {}", request.getRequestURL(), String.join("\r\n\r\tat ", stackTraceArray[1]));

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if (WebMvcHelper.skipIntercept(request, handler)) {
            return;
        }

        String requestId = response.getHeader(ApplicationConstant.RESPONSE_IDENTITY);
        log.debug("当前请求结束 {}={}", ApplicationConstant.RESPONSE_IDENTITY, requestId);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (WebMvcHelper.skipIntercept(request, handler)) {
            return;
        }

        // 清理当前HTTP请求线程缓存
        WebMvcHelper.clearThreadCache();
    }
}
